package org.eclipse.iota.util;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.iota.model.Alternation;
import org.eclipse.iota.model.BinaryOperation;
import org.eclipse.iota.model.Clause;
import org.eclipse.iota.model.Constraint;
import org.eclipse.iota.model.Definition;
import org.eclipse.iota.model.Expression;
import org.eclipse.iota.model.MultiOperation;
import org.eclipse.iota.model.Operation;
import org.eclipse.iota.model.UnaryOperation;

/**
 * Copy methods for Iota models.
 * @author Christian Krause
 * @generated NOT
 */
public class IotaCopyUtil {

	/**
	 * Copy a definition.
	 * @param definition Definition to be copied.
	 * @return The copy.
	 */
	public static <T extends Definition> T copy(T definition) {
		return (T) EcoreUtil.copy(definition);
	}

	/**
	 * Copy an alternation.
	 * @param alternation Alternation to be copied.
	 * @return The copy.
	 */
	public static Alternation copy(Alternation alternation) {
		return (Alternation) EcoreUtil.copy(alternation);
	}

	/**
	 * Copy a clause.
	 * @param clause Clause to be copied.
	 * @return The copy.
	 */
	public static Clause copy(Clause clause) {
		return (Clause) EcoreUtil.copy(clause);
	}

	/**
	 * Copy a constraint.
	 * @param constraint Constraint to be copied.
	 * @return The copy.
	 */
	public static <T extends Constraint> T copy(T constraint) {
		return (T) EcoreUtil.copy(constraint);
	}

	/**
	 * Copy an expression.
	 * @param expression Expression to be copied.
	 * @return The copy.
	 */
	public static <T extends Expression> T copy(T expression) {
		return (T) EcoreUtil.copy(expression);
	}

	/**
	 * Copy the operands of an operation.
	 * @param operation Operation.
	 * @return Modifiable list of operands.
	 */
	public static List<Expression> copyOperands(Operation operation) {
		List<Expression> result = new ArrayList<Expression>();
		if (operation instanceof MultiOperation) {
			result.addAll(((MultiOperation) operation).getOperands());
		}
		else if (operation instanceof BinaryOperation) {
			result.add(((BinaryOperation) operation).getLeft());
			result.add(((BinaryOperation) operation).getRight());
		}
		else if (operation instanceof UnaryOperation) {
			result.add(((UnaryOperation) operation).getOperand());
		}
		else {
			throw new RuntimeException("Unknown operation type: " + operation.getClass().getSimpleName());
		}
		return result;
	}
}
